namespace Romer
{
    using Romer.Properties;
    using System;
    using System.Drawing;
    using System.IO;
    using System.Text;
    using System.Windows.Forms;

    internal class NdsIconBuilder
    {
        private byte[] bNDSPalette = new byte[0x20];
        public Bitmap BuildBitmap = new Bitmap(0x20, 0x20);
        public Color[] BuildPalette = new Color[0x10];
        private bool checksum;
        private bool forcecrc;
        private bool headersize;
        private bool lenpointer;
        public string NdsFile = "";
        public string NewCountryCode = "";
        public string NewEmbedTitle = "";
        public string NewRomTitle = "";
        public string NewVersion = "";
        public byte[] RAWIcon = new byte[0x840];
        private bool unitcode;

        public bool BuildNdsIcon(Bitmap InputImage)
        {
            Color pixel = new Color();
            int[,] paletteArray = new int[0x10, 3];
            int[,] numArray2 = new int[0x20, 0x20];
            string[] strArray = new string[0x10];
            if (Convert.ToInt32(InputImage.Palette.Entries.GetLength(0)) == 0x10)
            {
                for (int i = 0; i < 0x10; i++)
                {
                    paletteArray[i, 0] = InputImage.Palette.Entries[15 - i].R;
                    paletteArray[i, 1] = InputImage.Palette.Entries[15 - i].G;
                    paletteArray[i, 2] = InputImage.Palette.Entries[15 - i].B;
                }
                for (int j = 0; j < 0x20; j++)
                {
                    for (int num4 = 0; num4 < 0x20; num4++)
                    {
                        pixel = InputImage.GetPixel(j, num4);
                        numArray2[j, num4] = this.SelectPallete(pixel, paletteArray);
                    }
                }
                for (int k = 0; k < 0x10; k++)
                {
                    strArray[k] = this.RGBtoBitString(paletteArray[k, 0], paletteArray[k, 1], paletteArray[k, 2]);
                }
                string[] strArray2 = new string[0x20];
                int index = 0;
                for (int m = 0; m < 0x10; m++)
                {
                    strArray2[index] = strArray[m].Substring(0, 8);
                    strArray2[index + 1] = strArray[m].Substring(8, 8);
                    index += 2;
                }
                for (int n = 0; n < 0x20; n++)
                {
                    this.RAWIcon[0x220 + n] = Convert.ToByte(this.InvertString(strArray2[n]), 2);
                }
                int num9 = 0;
                for (int num10 = 0; num10 < 0x10; num10++)
                {
                    for (int num11 = (num10 / 4) * 8; num11 < (((num10 / 4) * 8) + 8); num11++)
                    {
                        for (int num12 = (num10 % 4) * 8; num12 < (((num10 % 4) * 8) + 8); num12++)
                        {
                            string input = "";
                            if ((num12 % 2) != 1)
                            {
                                input = input + this.ValueTo4BitString(numArray2[num12 + 1, num11]) + this.ValueTo4BitString(numArray2[num12, num11]);
                                this.InvertString(input);
                                this.RAWIcon[num9 + 0x20] = Convert.ToByte(input, 2);
                                num9++;
                            }
                        }
                    }
                }
                this.WriteEmbedTitle();
                this.WriteRomTitle();
                this.WriteCountryCode();
                byte[] buffer = new byte[2];
                byte[] bytes = new byte[2];
                bytes = BitConverter.GetBytes(1);
                this.RAWIcon[0] = bytes[0];
                this.RAWIcon[1] = bytes[1];
                buffer = BitConverter.GetBytes(this.GetBannerCRC());
                this.RAWIcon[2] = buffer[0];
                this.RAWIcon[3] = buffer[1];
                return true;
            }
            MessageBox.Show("Error: Bitmap must be 32 x 32 and have a pallete of 16 colours.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Hand);
            this.NdsFile = "";
            return false;
        }

        public bool BuildNdsIconNoImage()
        {
            this.RAWIcon = new NdsIcon { NdsFile = this.NdsFile }.ReadRawIcon();
            this.WriteEmbedTitle();
            this.WriteRomTitle();
            this.WriteCountryCode();
            byte[] buffer = new byte[2];
            byte[] bytes = new byte[2];
            bytes = BitConverter.GetBytes(1);
            this.RAWIcon[0] = bytes[0];
            this.RAWIcon[1] = bytes[1];
            buffer = BitConverter.GetBytes(this.GetBannerCRC());
            this.RAWIcon[2] = buffer[0];
            this.RAWIcon[3] = buffer[1];
            return true;
        }

        public void FixHeaderAndLogoCRC()
        {
            byte[] array = new byte[350];
            byte[] p = new byte[0x9c];
            byte[] buffer3 = new byte[0x160];
            CRCTool tool = new CRCTool();
            tool.Init(CRCTool.CRCCode.CRC16);
            FileStream input = new FileStream(this.NdsFile, FileMode.Open);
            BinaryReader reader = new BinaryReader(input) {
                BaseStream = { Position = 0L }
            };
            array = reader.ReadBytes(350);
            reader.BaseStream.Position = 0L;
            buffer3 = reader.ReadBytes(0x160);
            reader.BaseStream.Position = 0xc0L;
            p = reader.ReadBytes(0x9c);
            if (Settings.Default.forcelogo)
            {
                p = NintendoLogo();
            }
            p.CopyTo(array, 0xc0);
            byte[] bytes = new byte[4];
            if (Settings.Default.headersize)
            {
                bytes = BitConverter.GetBytes(input.Length);
                array[0x80] = bytes[0];
                array[0x81] = bytes[1];
                array[130] = bytes[2];
                array[0x83] = bytes[3];
            }
            input.Close();
            if (Settings.Default.checksum)
            {
                bytes = BitConverter.GetBytes(tool.crcbitbybit(p));
                array[0x15c] = bytes[0];
                array[0x15d] = bytes[1];
            }
            new UTF8Encoding().GetBytes("KX", 0, 2, bytes, 0);
            array[0x10] = bytes[0];
            array[0x11] = bytes[1];
            if (Settings.Default.unitcode)
            {
                bytes = BitConverter.GetBytes(0);
                array[0x12] = bytes[0];
            }
            if (Settings.Default.headersize)
            {
                bytes = BitConverter.GetBytes(0x4000);
                array[0x84] = bytes[0];
                array[0x85] = bytes[1];
                array[0x86] = bytes[2];
                array[0x87] = bytes[3];
            }
            array.CopyTo(buffer3, 0);
            if (Settings.Default.checksum)
            {
                bytes = BitConverter.GetBytes(tool.crcbitbybit(array));
                buffer3[350] = bytes[0];
                buffer3[0x15f] = bytes[1];
            }
            FileStream output = new FileStream(this.NdsFile, FileMode.Open);
            new BinaryWriter(output) { BaseStream = { Position = 0L } }.Write(buffer3);
            output.Close();
        }

        public ulong GetBannerCRC()
        {
            byte[] p = new byte[0x820];
            for (int i = 0; i < 0x820; i++)
            {
                p[i] = this.RAWIcon[i + 0x20];
            }
            CRCTool tool = new CRCTool();
            tool.Init(CRCTool.CRCCode.CRC16);
            return tool.crcbitbybit(p);
        }

        public string InvertString(string input)
        {
            string str = "";
            for (int i = 0; i < input.Length; i++)
            {
                string str2 = "";
                str2 = input.Substring(input.Length - (i + 1), 1);
                str = str + str2;
            }
            return str;
        }

        private static byte[] NintendoLogo()
        {
            return new byte[] { 
                0x24, 0xff, 0xae, 0x51, 0x69, 0x9a, 0xa2, 0x21, 0x3d, 0x84, 130, 10, 0x84, 0xe4, 9, 0xad, 
                0x11, 0x24, 0x8b, 0x98, 0xc0, 0x81, 0x7f, 0x21, 0xa3, 0x52, 190, 0x19, 0x93, 9, 0xce, 0x20, 
                0x10, 70, 0x4a, 0x4a, 0xf8, 0x27, 0x31, 0xec, 0x58, 0xc7, 0xe8, 0x33, 130, 0xe3, 0xce, 0xbf, 
                0x85, 0xf4, 0xdf, 0x94, 0xce, 0x4b, 9, 0xc1, 0x94, 0x56, 0x8a, 0xc0, 0x13, 0x72, 0xa7, 0xfc, 
                0x9f, 0x84, 0x4d, 0x73, 0xa3, 0xca, 0x9a, 0x61, 0x58, 0x97, 0xa3, 0x27, 0xfc, 3, 0x98, 0x76, 
                0x23, 0x1d, 0xc7, 0x61, 3, 4, 0xae, 0x56, 0xbf, 0x38, 0x84, 0, 0x40, 0xa7, 14, 0xfd, 
                0xff, 0x52, 0xfe, 3, 0x6f, 0x95, 0x30, 0xf1, 0x97, 0xfb, 0xc0, 0x85, 0x60, 0xd6, 0x80, 0x25, 
                0xa9, 0x63, 190, 3, 1, 0x4e, 0x38, 0xe2, 0xf9, 0xa2, 0x34, 0xff, 0xbb, 0x3e, 3, 0x44, 
                120, 0, 0x90, 0xcb, 0x88, 0x11, 0x3a, 0x94, 0x65, 0xc0, 0x7c, 0x63, 0x87, 240, 60, 0xaf, 
                0xd6, 0x25, 0xe4, 0x8b, 0x38, 10, 0xac, 0x72, 0x21, 0xd4, 0xf8, 7
             };
        }

        public string RGBtoBitString(int red, int green, int blue)
        {
            string str = "";
            return ((str + this.ValueTo5BitString(red) + this.ValueTo5BitString(green)) + this.ValueTo5BitString(blue) + "0");
        }

        private int SelectPallete(Color color, int[,] PaletteArray)
        {
            for (int i = 0; i < 0x10; i++)
            {
                string str = Convert.ToString(PaletteArray[i, 0]) + Convert.ToString(PaletteArray[i, 1]) + Convert.ToString(PaletteArray[i, 2]);
                string str2 = Convert.ToString(color.R) + Convert.ToString(color.G) + Convert.ToString(color.B);
                if (str == str2)
                {
                    return i;
                }
            }
            return 0;
        }

        public void SetOptions(bool checksumO, bool lenpointerO, bool unitcodeO, bool headersizeO, bool forcecrcO)
        {
            this.checksum = checksumO;
            this.lenpointer = lenpointerO;
            this.unitcode = unitcodeO;
            this.headersize = headersizeO;
            this.forcecrc = forcecrcO;
        }

        public byte[] StringtoU16(string Input)
        {
            UnicodeEncoding encoding = new UnicodeEncoding(false, true, true);
            byte[] buffer = new byte[0x100];
            return encoding.GetBytes(Input);
        }

        public string ValueTo4BitString(int input)
        {
            string str = "";
            for (int i = 0; i < 4; i++)
            {
                int num2 = input - Convert.ToInt16(Math.Pow(2.0, (double) (3 - i)));
                if (num2 >= 0)
                {
                    str = str + "1";
                    input -= Convert.ToInt16(Math.Pow(2.0, (double) (3 - i)));
                }
                else
                {
                    str = str + "0";
                }
            }
            return str;
        }

        public string ValueTo5BitString(int input)
        {
            float num = input;
            num = (num / 255f) * 31f;
            input = Convert.ToInt16(num);
            string str = "";
            for (int i = 0; i < 5; i++)
            {
                int num3 = input - Convert.ToInt16(Math.Pow(2.0, (double) (4 - i)));
                if (num3 >= 0)
                {
                    str = str + "1";
                    input -= Convert.ToInt16(Math.Pow(2.0, (double) (4 - i)));
                }
                else
                {
                    str = str + "0";
                }
            }
            return this.InvertString(str);
        }

        private void WriteCountryCode()
        {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] bytes = new byte[4];
            string s = this.NewCountryCode.PadRight(4, 'X');
            encoding.GetBytes(s, 0, 4, bytes, 0);
            FileStream stream = new FileStream(this.NdsFile, FileMode.Open) {
                Position = 12L
            };
            stream.Write(bytes, 0, 4);
            stream.Close();
        }

        public void WriteEmbedTitle()
        {
            int num = 0x240;
            byte[] array = new byte[0x100];
            array = this.StringtoU16(this.NewEmbedTitle);
            Array.Resize<byte>(ref array, 0x100);
            for (int i = this.NewEmbedTitle.Length * 2; i < 0x100; i++)
            {
                array[i] = 0;
            }
            for (int j = 0; j < 6; j++)
            {
                array.CopyTo(this.RAWIcon, (int) (num + (0x100 * j)));
            }
        }

        private void WriteRomTitle()
        {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] bytes = new byte[12];
            string s = this.NewRomTitle.PadRight(12, ' ');
            encoding.GetBytes(s, 0, 11, bytes, 0);
            FileStream stream = new FileStream(this.NdsFile, FileMode.Open) {
                Position = 0L
            };
            stream.Write(bytes, 0, 12);
            stream.Close();
        }
    }
}

